﻿using Net.Server;
using Net.Share;
using WordGames.System;
using WordGames.Service;
using Wordgames;
using Net;
using Cysharp.Threading.Tasks;

namespace WordGames
{
    internal class GateService : TcpServer<GatePeer>
    {
        protected override void OnStartupCompleted()
        {
            base.OnStartupCompleted();
            OnNetworkDataTraffic += (df) =>
            {
                Console.Title = $"Gate {Port} {df}";
            };
        }

        protected override void OnRpcExecute(GatePeer client, IRpcModel model)
        {
            _ = OnMessageHandler(client, model);
        }

        public async override UniTask OnMessageHandler(ClientUnitBase self, IRpcModel model)
        {
            switch ((ProtoType)model.Protocol)
            {
                case ProtoType.Register:
                    {
                        var client = self as GatePeer;
                        var token = client.Token;
                        var account = model.AsString;
                        var password = model.AsString;
                        var cluster = ClusterSystem.GetCluster<LoginService>(this);
                        var code = await cluster.GetHashing(account).Request<int>(ProtoType.Register, GlobalConfig.RequestTimeout, account, password);
                        Response(client, ProtoType.Register, token, code);
                    }
                    break;
                case ProtoType.Login:
                    {
                        var client = self as GatePeer;
                        var token = client.Token;
                        var account = model.AsString;
                        var password = model.AsString;
                        var cluster = ClusterSystem.GetCluster<LoginService>(this);
                        var (code, user) = await cluster.GetHashing(account).Request<int, UserData>(ProtoType.Login, GlobalConfig.RequestTimeout, account, password);
                        Response(client, ProtoType.Login, token, code, user);
                        if (code == 1)
                        {
                            cluster = ClusterSystem.GetCluster<GameService>(this);
                            client.GameSession = cluster.GetHashing(account);
                            client.Account = account;
                            client.UserId = user.Id;
                        }
                    }
                    break;
                case ProtoType.PlayerEnterGame:
                    {
                        var client = self as GatePeer;
                        var token = client.Token;
                        var userId = client.UserId;
                        var remoteId = client.RemoteId;
                        var account = client.Account;
                        var gateRoute = client.GameSession.Local;
                        var code = await client.GameSession.Request<int>(ProtoType.PlayerEnterGame, GlobalConfig.RequestTimeout, userId, remoteId, account, gateRoute);
                        Response(client, ProtoType.PlayerEnterGame, token, code);
                    }
                    break;
                case ProtoType.SetPlayerName:
                    {
                        var client = self as GatePeer;
                        var token = client.Token;
                        var userId = client.UserId;
                        var name = model.AsString;
                        var code = await client.GameSession.Request<int>(ProtoType.SetPlayerName, GlobalConfig.RequestTimeout, userId, name);
                        Response(client, ProtoType.SetPlayerName, token, code);
                    }
                    break;
                case ProtoType.SetPlayerName_GameToGate:
                    {
                        var remoteId = model.AsLong;
                        if (Clients.TryGetValue(remoteId, out var gateClient))
                            gateClient.Call(ProtoType.SetPlayerName, 1);
                    }
                    break;
                case ProtoType.SignOut_GameToGate:
                    {
                        var remoteId = model.AsLong;
                        var name = model.AsString;
                        if (Clients.TryGetValue(remoteId, out var gateClient))
                            gateClient.Call(ProtoType.SignOut, name);
                    }
                    break;
                case ProtoType.WorldChat:
                    {
                        var client = self as GatePeer;
                        var userId = client.UserId;
                        var message = model.AsString;
                        client.GameSession.Call(ProtoType.WorldChat, userId, message);
                    }
                    break;
                case ProtoType.WorldChat_GameToGate:
                    {
                        var remoteId = model.AsLong;
                        var name = model.AsString;
                        var message = model.AsString;
                        if (Clients.TryGetValue(remoteId, out var gateClient))
                            gateClient.Call(ProtoType.WorldChat, name, message);
                    }
                    break;
            }
        }
    }
}
